/*
 * Date：10/23/18 10:15 PM
 * Author: guomw
 *
 */

package org.elanfox.intellicommunity.biz.service.core.resident.impl;

import org.apache.commons.lang3.StringUtils;
import org.elanfox.intellicommunity.biz.dto.redis.RedisRoomDTO;
import org.elanfox.intellicommunity.biz.dto.resident.RoomSaveDTO;
import org.elanfox.intellicommunity.biz.entity.equipment.LocatorPO;
import org.elanfox.intellicommunity.biz.entity.resident.ResidentPO;
import org.elanfox.intellicommunity.biz.entity.resident.RoomPO;
import org.elanfox.intellicommunity.biz.entity.resident.RoomPO_;
import org.elanfox.intellicommunity.biz.repository.resident.RoomRepository;
import org.elanfox.intellicommunity.biz.service.core.equipment.LocatorService;
import org.elanfox.intellicommunity.biz.service.core.resident.ResidentService;
import org.elanfox.intellicommunity.biz.service.core.resident.RoomService;
import org.elanfox.intellicommunity.common.constant.RedisConstant;
import org.elanfox.intellicommunity.data.base.base.AbstractSearchableCrudService;
import org.elanfox.intellicommunity.data.base.base.SpecificationAndSort;
import org.elanfox.intellicommunity.data.base.dto.BaseSaveDTO;
import org.elanfox.intellicommunity.data.base.dto.BaseSearchDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 用户相关service
 *
 * @author loutianxi
 * @date 2019-12-05
 */
@Service
public class RoomServiceImpl extends AbstractSearchableCrudService<RoomPO, Integer> implements RoomService {

    @Autowired
    private RoomRepository repository;
    @Autowired
    private LocatorService locatorService;
    @Autowired
    private ResidentService residentService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    protected RoomServiceImpl(RoomRepository repository) {
        super(repository);
    }

    @Override
    protected SpecificationAndSort<RoomPO> specificationAndSort(BaseSearchDTO condition) {
        Specification<RoomPO> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            predicates.add(cb.isTrue(root.get(RoomPO_.delFlag)));
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        return new SpecificationAndSort<>(specification, sort);
    }

    @Override
    public RoomPO save(BaseSaveDTO saveDTO) {
        RoomSaveDTO roomSaveDTO = (RoomSaveDTO) saveDTO;
        //验证房间号是否已经存在
        sole(roomSaveDTO.getRoomId(), roomSaveDTO.getRoomName());
        //房间需要关联定位器
        if (roomSaveDTO.getLocatorNo() != null) {
            LocatorPO locatorPO = locatorService.findByNo(roomSaveDTO.getLocatorNo());
            if (locatorPO == null) {
                throw new IllegalStateException("请输入系统中已录入设备的编号");
            }
        }
        RoomPO roomPO;
        if (roomSaveDTO.getRoomId() == null) {
            roomPO = new RoomPO();
            roomPO.setRoomName(roomSaveDTO.getRoomName());
            roomPO.setDescribe(roomSaveDTO.getDescribe());
            roomPO.setEquNo(roomSaveDTO.getLocatorNo());
        } else {
            roomPO = findById(((RoomSaveDTO) saveDTO).getRoomId());
        }
        roomPO.setAddress(roomSaveDTO.getAddress());
        roomPO.setStructureId(roomSaveDTO.getStructureId());
        roomPO.setLatitude(roomSaveDTO.getLatitude());
        roomPO.setLongitude(roomSaveDTO.getLongitude());
        roomPO = repository.save(roomPO);
        //加入到redis
        redisTemplate.opsForHash().put(RedisConstant.KEY_ROOM, "room_" + roomPO.getRoomName(), new RedisRoomDTO(roomPO));
        return roomPO;
    }

    /**
     * 验证唯一性
     *
     * @return
     */
    private void sole(Integer roomId, String roomName) {
        if (StringUtils.isEmpty(roomName)) {
            return;
        }
        RoomPO roomPO = repository.findByRoomNameAndDelFlagIsTrue(roomName);
        //新增
        if (roomId == null && roomPO != null) {
            throw new IllegalStateException("房间编号已存在");
        }
        if (roomId != null && roomPO.getRoomId().equals(roomId)) {
            throw new IllegalStateException("房间编号已存在");
        }
    }

    @Override
    public List<RoomPO> findByStrId(Integer strId) {
        return repository.findByStructureIdAndDelFlagIsTrue(strId);
    }



    @Override
    public boolean delete(Integer id) {
        RoomPO roomPO = findById(id);
        //第一步：判断房间是否被关联
        List<ResidentPO> residentPOS = residentService.findByRoomNumber(roomPO.getRoomName());
        if (!CollectionUtils.isEmpty(residentPOS)) {
            throw new IllegalStateException("房间存在关联用户，请先取消关联");
        }
        roomPO.setDelFlag(false);
        roomPO.setUpdateTime(LocalDateTime.now());
        repository.save(roomPO);

        //从redis中删除
        redisTemplate.opsForHash().delete(RedisConstant.KEY_ROOM, "room_" + roomPO.getRoomName());
        return true;
    }
}
